use redis::{Commands, Connection, RedisError};
use std::result::Result;

const REDIS_PREFIX_SOURCE: &str = "img_code_source";
const REDIS_CODE_SOURCE_DURATION: usize = 600;

pub fn set_data_str(
    redis_conn: &mut Connection,
    data_prefix: &str,
    key: &str,
    data: &str,
) -> Result<(), RedisError> {
    redis_conn.set(format!("{}:{}", data_prefix, key), data)
}

pub fn set_code_source(
    redis_conn: &mut Connection,
    key: &str,
    data: &str,
) -> Result<(), RedisError> {
    redis_conn.set_ex(
        format!("{}:{}", REDIS_PREFIX_SOURCE, key),
        data,
        REDIS_CODE_SOURCE_DURATION,
    )
}

pub fn exists_code_source(redis_conn: &mut Connection, key: &str) -> Result<bool, RedisError> {
    redis_conn.exists(format!("{}:{}", REDIS_PREFIX_SOURCE, key))
}

pub fn exists_data(
    redis_conn: &mut Connection,
    data_prefix: &str,
    key: &str,
) -> Result<bool, RedisError> {
    redis_conn.exists(format!("{}:{}", data_prefix, key))
}

pub struct Auth<'a> {
    redis_conn: &'a mut Connection,
}

impl<'a> Auth<'a> {
    const PREFIX: &str = "auth";
    pub fn from(redis_conn: &'a mut Connection) -> Self {
        Self { redis_conn }
    }

    pub fn build_key(access_code: &str) -> String {
        format!("{}:{}", Self::PREFIX, access_code)
    }

    pub fn set_access_code(
        &'a mut self,
        access_code: &str,
        user_id: &str,
    ) -> Result<(), RedisError> {
        self.redis_conn.set(&Self::build_key(access_code), user_id)
    }
    pub fn is_authed(&'a mut self, access_code: &str) -> Result<bool, RedisError> {
        self.redis_conn.exists(Self::build_key(access_code))
    }
    pub fn get_user_id(&'a mut self, access_code: &str) -> Result<String, RedisError> {
        self.redis_conn.get(Self::build_key(access_code))
    }
}
